package com.bkck.sharkblockade.levels.level;

import java.util.ArrayList;
import java.util.List;
import com.bkck.sharkblockade.menu.R;
import com.bkck.sharkblockade.levels.LevelSelection;
import com.bkck.sharkblockade.levels.ball.Ball;
import com.bkck.sharkblockade.levels.block.Block;
import com.bkck.sharkblockade.levels.harpoon.Harpoon;
import com.bkck.sharkblockade.levels.item.Item;
import com.bkck.sharkblockade.levels.paddle.Paddle;
import com.bkck.sharkblockade.levels.shark.Shark;
import com.bkck.sharkblockade.levels.thread.MainGamePanel;
import com.bkck.sharkblockade.levels.thread.MainThread;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;

/**
 * The level one page.
 * 
 * @author Team BKCK.
 * 
 */
public class Level extends Activity {

  public static int level;

  private int numberJellyfish;
  private int numberSharks;
  private int numberFishes;

  // the log used for debugging
  public static final String TAG = Level.class.getSimpleName();

  // identifiers used to recognize different messages received from the running thread.
  public static final int TIMER_IDENTIFIER = 1;
  public static final int LIVES_IDENTIFIER = 2;
  public static final int SCORE_IDENTIFIER = 3;
  public static final int LOSE_IDENTIFIER = 4;
  public static final int WIN_IDENTIFIER = 5;

  // SurfaceView
  private static MainGamePanel gamePanel;

  // variables for game pause
  private boolean paused = false;
  private boolean dataSaved = false;

  // variables to display the game info on top.
  private static TextView timeDisplay;
  private static TextView score;
  private static TextView lives;
  private TextView levelName;

  // variables to store the game state when paused.
  private List<Block> blocks = new ArrayList<Block>();
  private Ball ball = new Ball();
  private Paddle paddle = new Paddle();
  private Shark blueShark = new Shark();
  private Shark orangeShark = new Shark();
  private Item item = new Item();
  private Harpoon harpoon = new Harpoon();
  private int gameScore;
  private int gameLives;

  // handler to handle messages from the running thread
  public static Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {

      switch (msg.what) {
      case TIMER_IDENTIFIER:
        timeDisplay.setText(formatTime((Long) msg.obj));
        break;
      case LIVES_IDENTIFIER:
        lives.setText(String.valueOf(msg.obj));
        break;
      case SCORE_IDENTIFIER:
        score.setText(String.valueOf(msg.obj));
        break;
      case WIN_IDENTIFIER:
        gamePanel.handleResult(true);
        break;
      case LOSE_IDENTIFIER:
        gamePanel.handleResult(false);
        break;
      }
    }
  };

  /**
   * Called when the activity is first created.
   */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // requesting to turn the title OFF
    requestWindowFeature(Window.FEATURE_NO_TITLE);

    // making it full screen
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
        WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(R.layout.level);

    levelName = (TextView) findViewById(R.id.levelName);

    if (level == 1) {
      levelName.setText("Level One");
      numberJellyfish = 1;
      numberSharks = 0;
      numberFishes = 0;
    }
    if (level == 2) {
      levelName.setText("Level Two");
      numberJellyfish = 0;
      numberSharks = 1;
      numberFishes = 0;
    }
    if (level == 3) {
      levelName.setText("Level Three");
      numberJellyfish = 2;
      numberSharks = 1;
      numberFishes = 0;
    }
    if (level == 4) {
      levelName.setText("Level Four");
      numberJellyfish = 1;
      numberSharks = 2;
      numberFishes = 1;
    }
    if (level == 5) {
      levelName.setText("Level Five");
      numberJellyfish = 2;
      numberSharks = 2;
      numberFishes = 1;
    }

    // map variables to resources
    timeDisplay = (TextView) findViewById(R.id.actualTime);
    score = (TextView) findViewById(R.id.actualScore);
    lives = (TextView) findViewById(R.id.lives);
    gamePanel = (MainGamePanel) findViewById(R.id.gamePanel);

    Log.d(TAG, "Level in onCreate");
  }

  /**
   * Store the current game data prior to shutting down the thread. So we can restore the game on
   * resume.
   */
  private void storeCurrentGameData() {
    Log.d(TAG, "Storing game data");

    // store the game state
    blocks = gamePanel.getBlocks();
    ball = gamePanel.getBall();
    paddle = gamePanel.getPaddle();
    blueShark = gamePanel.getBlueShark();
    orangeShark = gamePanel.getOrangeShark();
    item = gamePanel.getItem();
    harpoon = gamePanel.getHarpoon();

    gameScore = MainThread.getScore();
    gameLives = MainThread.getLives();

    // data was successfully saved.
    dataSaved = true;
  }

  /**
   * Retrieve the saved data so the player can start where he left off before pausing the game.
   */
  private void restoreGameData() {
    Log.d(TAG, "Restoring game data");

    // restore the blocks
    gamePanel.setBlocks(blocks);

    // restore the ball
    ball.setLastUpdateTime(-1);
    gamePanel.setBall(ball);

    // restore the paddle
    gamePanel.setPaddle(paddle);

    // restore the blue shark
    if (blueShark != null) {
      blueShark.setLastUpdateTime(-1);
      gamePanel.setBlueShark(blueShark);
    }

    // restore the orange shark
    if (orangeShark != null) {
      orangeShark.setLastUpdateTime(-1);
      gamePanel.setOrangeShark(orangeShark);
    }

    // restore the item
    item.setLastUpdateTime(-1);
    gamePanel.setItem(item);

    // restore the harpoon
    harpoon.setLastUpdateTime(-1);
    gamePanel.setHarpoon(harpoon);

    // resume thread after the game state is restored
    gamePanel.resumeThread(gameLives, gameScore);
  }

  /**
   * Display the pause menu. It's called in onResume method.
   */
  private void showPausedMenu() {
    // store game data and end thread
    if (!dataSaved) {
      storeCurrentGameData();
    }
    gamePanel.shutdownThread();

    // initialize dialog and its layout
    final Dialog dialog = new Dialog(this);
    dialog.setContentView(R.layout.exit_box);
    dialog.setTitle("    Paused");

    // create buttons and add onClickListeners to them.
    Button resumeButton = (Button) dialog.findViewById(R.id.resumeButton);
    Button restartButton = (Button) dialog.findViewById(R.id.restartButton);
    Button exitButton = (Button) dialog.findViewById(R.id.exitButton);

    // go back to LevelSelection page on click.
    exitButton.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        dataSaved = false;
        dialog.dismiss();
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setClassName(Level.this, LevelSelection.class.getName());
        // end thread and change activity
        startActivity(intent);
      }
    });

    // restart the current level.
    restartButton.setOnClickListener(new View.OnClickListener() {

      public void onClick(View v) {
        dataSaved = false;
        dialog.dismiss();
        gamePanel.resetGame();
      }
    });

    // resume game.
    resumeButton.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        dataSaved = false;
        dialog.dismiss();
        // read in stored game data and then resume
        restoreGameData();
      }
    });

    // player has to click on one of the button in order to cancel the dialog.
    dialog.setCancelable(false);
    dialog.show();
  }

  /**
   * Show the paused menu, called when user click on exit.
   * 
   * @param view The view.
   */
  public void showPausedMenu(View view) {
    showPausedMenu();
  }

  /**
   * Takes in time elapsed in milliseconds and convert it to String 00:00 (MIN:SEC)
   * 
   * @param milliseconds
   * @return
   */
  public static String formatTime(long milliseconds) {
    String minuteString = "00";
    String secondString = "00";

    long seconds = milliseconds / 1000;
    long minutes = seconds / 60;
    seconds = seconds % 60;

    if (seconds < 10) {
      secondString = "0" + seconds;
    }
    else {
      secondString = String.valueOf(seconds);
    }

    if (minutes < 10) {
      minuteString = "0" + minutes;
    }
    else {
      minuteString = String.valueOf(minutes);
    }

    return minuteString + ":" + secondString;
  }

  /**
   * Ignore screen orientation change.
   */
  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
  }

  /**
   * onResume is always called during each lifecycle. So it's better that we initialize the game
   * objects in here.
   */
  @Override
  protected void onResume() {

    if (paused) {
      Log.d(TAG, "Game was paused");
      showPausedMenu();
    }
    else {
      Log.d(TAG, "It's a new game");
      // no need to retrieve game data.
      gamePanel.initializeObjects(numberSharks, level, numberJellyfish, numberFishes);
      // gamePanel.initializeObjects(numberSharks, level, numberJellyfish, numberFishes);
    }

    Log.d(TAG, "Level in onResume");
    super.onResume();
  }

  /**
   * Invoked when we call finish(). Performs a cleanup and destroys this activity. It's also invoked
   * when the device has low memory and needs to kill a process.
   */
  @Override
  protected void onDestroy() {
    paused = false;
    Log.d(TAG, "Level in onDestroy");
    super.onDestroy();

  }

  /**
   * Called when this activity is no longer visible to the user. It's always followed by onRestart
   * or onDestroy.
   */
  @Override
  protected void onStop() {
    Log.d(TAG, "Level in onStop");

    finish();
    onDestroy();

    if (gamePanel.goToNextLevel()) {
      Level.level += 1;
      Intent intent = new Intent(Intent.ACTION_VIEW);
      intent.setClassName(Level.this, Level.class.getName());
      startActivity(intent);
    }
  }

  /**
   * Called in every lifecycle before onStop and onDestroy. This is where we should save the game
   * data.
   */
  @Override
  protected void onPause() {

    // save game data and end the thread.
    storeCurrentGameData();
    paused = true;
    gamePanel.shutdownThread();
    super.onPause();

  }

}